package com.fabolab.jetset.core.security;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fabolab.jetset.core.config.ConfigurationManager;
import com.fabolab.jetset.core.config.model.User;
import com.fabolab.jetset.core.config.model.Users;

public class XmlRealm extends RealmBase {

	 protected static final String info =
		        "com.fabolab.jetset.core.security.XmlRealm/1.0";


		    /**
		     * Descriptive information about this Realm implementation.
		     */

		    protected static final String name = "XmlRealm";


		    /**
		     * The pathname (absolute or relative to JetSet's current working
		     * directory) of the XML file containing our database information.
		     */
		    private String pathname = "conf/users.xml";


		    /**
		     * The set of valid Principals for this Realm, keyed by user name.
		     */
		    private Map<String,GenericPrincipal> principals =
		        new HashMap<String,GenericPrincipal>();


		    private ConfigurationManager configurationManager;
		    // ------------------------------------------------------------- Properties


		    /**
		     * Return descriptive information about this Realm implementation and
		     * the corresponding version number, in the format
		     * <code>&lt;description&gt;/&lt;version&gt;</code>.
		     */
		    @Override
		    public String getInfo() {

		        return info;

		    }


		    /**
		     * Return the pathname of our XML file containing user definitions.
		     */
		    public String getPathname() {

		        return pathname;

		    }


		    /**
		     * Set the pathname of our XML file containing user definitions.  If a
		     * relative pathname is specified, it is resolved against "catalina.base".
		     *
		     * @param pathname The new pathname
		     */
		    public void setPathname(String pathname) {

		        this.pathname = pathname;

		    }


		    // --------------------------------------------------------- Public Methods

		    public XmlRealm(ConfigurationManager configurationManager,InputStream inputStream){
		    	this.configurationManager = configurationManager;  	
		    	Users users= configurationManager.parseUsersXml(inputStream);
				List<User> list = users.getUserList();
				for(User user : list){
					addUser(user);
				}
		    	
		    }

		    /**
		     * Return the Principal associated with the specified username and
		     * credentials, if there is one; otherwise return <code>null</code>.
		     *
		     * @param username Username of the Principal to look up
		     * @param credentials Password or other credentials to use in
		     *  authenticating this username
		     */
		    @Override
		    public Principal authenticate(String username, String credentials) {

		        GenericPrincipal principal = principals.get(username);

		        boolean validated = false;
		        if (principal != null && credentials != null) {
		            if (hasMessageDigest()) {
		                // Hex hashes should be compared case-insensitive
		                validated = (digest(credentials)
		                             .equalsIgnoreCase(principal.getPassword()));
		            } else {
		                validated =
		                    (digest(credentials).equals(principal.getPassword()));
		            }
		        }

		        if (validated) {
//		            if (log.isDebugEnabled())
//		                log.debug(sm.getString("memoryRealm.authenticateSuccess", username));
		            return (principal);
		        } else {
//		            if (log.isDebugEnabled())
//		                log.debug(sm.getString("memoryRealm.authenticateFailure", username));
		            return (null);
		        }

		    }


		    // -------------------------------------------------------- Package Methods


//		    /**
//		     * Add a new user to the in-memory database.
//		     *
//		     * @param username User's username
//		     * @param password User's password (clear text)
//		     * @param roles Comma-delimited set of roles associated with this user
//		     */
//		    void addUser(String username, String password, String roles) {
//
//		        // Accumulate the list of roles for this user
//		        ArrayList<String> list = new ArrayList<String>();
//		        roles += ",";
//		        while (true) {
//		            int comma = roles.indexOf(',');
//		            if (comma < 0)
//		                break;
//		            String role = roles.substring(0, comma).trim();
//		            list.add(role);
//		            roles = roles.substring(comma + 1);
//		        }
//
//		        // Construct and cache the Principal for this user
//		        GenericPrincipal principal =
//		            new GenericPrincipal(username, password, list);
//		        principals.put(username, principal);
//
//		    }

		    void addUser(User user) {

		        // Construct and cache the Principal for this user
		        GenericPrincipal principal =
		            new GenericPrincipal(user.getUserName(),user.getPassword(),user.getRoleNames());
		        principals.put(user.getUserName(), principal);

		    }


		    // ------------------------------------------------------ Protected Methods





		    /**
		     * Return a short name for this Realm implementation.
		     */
		    @Override
		    protected String getName() {

		        return (name);

		    }


		    /**
		     * Return the password associated with the given principal's user name.
		     */
		    @Override
		    protected String getPassword(String username) {

		        GenericPrincipal principal = principals.get(username);
		        if (principal != null) {
		            return (principal.getPassword());
		        } else {
		            return (null);
		        }

		    }


		    /**
		     * Return the Principal associated with the given user name.
		     */
		    @Override
		    protected Principal getPrincipal(String username) {

		        return principals.get(username);

		    }

		    /**
		     * Returns the principals for this realm.
		     *
		     * @return The principals, keyed by user name (a String)
		     */
		    protected Map<String,GenericPrincipal> getPrincipals() {
		        return principals;
		    }
}
